using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace Glpt.Data
{
    /// <summary>
    /// 数据库类别
    /// </summary>
    public enum DataBaseType
    {
        /// <summary>
        /// SQLServer
        /// </summary>
        SQLServer = 0,
        /// <summary>
        /// Oracle
        /// </summary>
        Oracle = 1,
        /// <summary>
        /// DB2
        /// </summary>
        DB2 = 2,
        /// <summary>
        /// MySQL
        /// </summary>
        MySQL = 3,
        /// <summary>
        /// SybaseIQ
        /// </summary>
        SybaseIQ = 4,
        /// <summary>
        /// PostgreSQL
        /// </summary>
        PostgreSQL = 5,
        /// <summary>
        /// SQLite
        /// </summary>
        SQLite = 6,
        /// <summary>
        /// MongoDB
        /// </summary>
        MongoDB = 7,
        /// <summary>
        /// Access
        /// </summary>
        Access = 8,
        /// <summary>
        /// DBF
        /// </summary>
        Dbf = 9,
        /// <summary>
        /// Kafka
        /// </summary>
        Kafka = 10,
        /// <summary>
        /// 达梦数据库
        /// </summary>
        DaMeng = 11,
        /// <summary>
        /// OceanBase
        /// </summary>
        OceanBase = 12,
        /// <summary>
        /// GoldenDB
        /// </summary>
        GoldenDB = 13,
        /// <summary>
        /// Kingbase
        /// </summary>
        Kingbase = 14,
        /// <summary>
        /// ClickHouse
        /// </summary>
        ClickHouse = 15,
        /// <summary>
        /// GaussDB
        /// </summary>
        GaussDB = 16,
        /// <summary>
        /// SybaseASE
        /// </summary>
        SybaseASE = 17,
        /// <summary>
        /// Teradata
        /// </summary>
        Teradata = 18,
        /// <summary>
        /// ODBC
        /// </summary>
        ODBC = 99
    }
    /// <summary>
    /// 数据库项目
    /// </summary>
    [Serializable]
    public class DbItem
    {
        /// <summary>
        /// 数据库编号
        /// </summary>
        public int DB_NO = 0;
        /// <summary>
        /// 子系统号
        /// </summary>
        public string SUB_SYSTEM = "";
        /// <summary>
        /// 数据库说明
        /// </summary>
        public string DB_TEXT = "";
        /// <summary>
        /// 数据库类别
        /// </summary>
        public DataBaseType DB_TYPE = DataBaseType.SQLServer;
        /// <summary>
        /// 数据库IP
        /// </summary>
        public string DB_IP = "";
        /// <summary>
        /// 数据库名称
        /// </summary>
        public string DB_NAME = "";
        /// <summary>
        /// 数据库用户
        /// </summary>
        public string USER_NAME = "";
        /// <summary>
        /// 数据库密码
        /// </summary>
        public string USER_PASSWORD = "";
        /// <summary>
        /// 集群组号
        /// </summary>
        public int GROUP_NO = 0;
        /// <summary>
        /// 是否使用代理
        /// </summary>
        public bool UseProxy = false;
        /// <summary>
        /// 代理数据库编号
        /// </summary>
        public int PROXY_DB_NO = 0;
        /// <summary>
        /// 映射用户名
        /// </summary>
        public string USER_MAP = "";
        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        public DbItem()
        {
        }

        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        /// <param name="db_type">数据库类别</param>
        /// <param name="db_name">数据库名称</param>
        public DbItem(DataBaseType db_type, string db_name)
        {
            DB_TYPE = db_type;
            DB_NAME = db_name;
        }

        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        /// <param name="db_type">数据库类别</param>
        /// <param name="db_name">数据库名称</param>
        /// <param name="db_ip">数据库IP</param>
        /// <param name="user_name">数据库用户</param>
        /// <param name="user_password">数据库密码</param>
        public DbItem(DataBaseType db_type, string db_name, string db_ip, string user_name, string user_password)
        {
            DB_TYPE = db_type;
            DB_NAME = db_name;
            DB_IP = db_ip;
            USER_NAME = user_name;
            USER_PASSWORD = user_password;
        }

        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        /// <param name="dr">数据行</param>
        public DbItem(DataRow dr)
        {
            int.TryParse(dr["DB_NO"].ToString(), out DB_NO);
            if (dr.Table.Columns.Contains("SUB_SYSTEM"))
                SUB_SYSTEM = dr["SUB_SYSTEM"].ToString();
            DB_TEXT = dr["DB_TEXT"].ToString();
            DB_TYPE = (DataBaseType)int.Parse(dr["DB_TYPE"].ToString());
            DB_IP = dr["DB_IP"].ToString();
            DB_NAME = dr["DB_NAME"].ToString();
            USER_NAME = dr["USER_NAME"].ToString();
            USER_PASSWORD = dr["USER_PASSWORD"].ToString();
            if (dr.Table.Columns.Contains("GROUP_NO"))
                int.TryParse(dr["GROUP_NO"].ToString(), out GROUP_NO);
            if (dr.Table.Columns.Contains("PROXY_DB_NO"))
                UseProxy = int.TryParse(dr["PROXY_DB_NO"].ToString(), out PROXY_DB_NO);
            if (dr.Table.Columns.Contains("USER_MAP"))
                USER_MAP = dr["USER_MAP"].ToString();
        }

        /// <summary>
        /// 获取数据库连接字符串
        /// </summary>
        /// <returns>连接字符串</returns>
        public String GetConnString()
        {
            string str = "";
            if (DB_TYPE.Equals(DataBaseType.SQLServer))
            {
                str = "Data Source=" + DB_IP;
                if (USER_NAME.Length == 0 && USER_PASSWORD.Length == 0)
                    str += ";Integrated Security=True";
                else
                {
                    str += ";Persist Security Info=True;User ID=" + USER_NAME;
                    str += ";Password=" + USER_PASSWORD;
                }
                str += ";Initial Catalog=" + DB_NAME;
            }
            else if (DB_TYPE.Equals(DataBaseType.Oracle))
            {
                string[] conn_ip_port = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=" + conn_ip_port[0];
                str += ")(PORT=" + (conn_ip_port.Length > 1 ? conn_ip_port[1] : "1521");
                str += ")))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=" + DB_NAME;
                str += ")));User Id=" + USER_NAME;
                str += ";Password=\"" + USER_PASSWORD + "\"";
            }
            else if (DB_TYPE.Equals(DataBaseType.DB2))
            {
                string[] conn_ip_port = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Server=" + conn_ip_port[0];
                str += ":" + (conn_ip_port.Length > 1 ? conn_ip_port[1] : "50000");
                str += ";Database=" + DB_NAME;
                str += ";User Id=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.MySQL))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Host=" + conn_ip_port_set[0];
                str += ";Port=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "3306");
                str += ";Database=" + DB_NAME;
                str += ";UserName=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
                str += ";CharSet=" + (conn_ip_port_set.Length > 2 ? conn_ip_port_set[2] : "utf8mb4") + ";SSL Mode=None;Allow User Variables=true;AllowLoadLocalInfile=true";
            }
            else if (DB_TYPE.Equals(DataBaseType.OceanBase) || DB_TYPE.Equals(DataBaseType.GoldenDB))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Host=" + conn_ip_port_set[0];
                str += ";Port=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "3306");
                str += ";Database=" + DB_NAME;
                str += ";UserName=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
                if (conn_ip_port_set.Length > 2) str += ";CharSet=" + conn_ip_port_set[2];
            }
            else if (DB_TYPE.Equals(DataBaseType.SybaseIQ))
            {
                str = "Host=" + DB_IP;
                str += ";DatabaseName=" + DB_NAME;
                str += ";UID=" + USER_NAME;
                str += ";PWD=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.PostgreSQL) || DB_TYPE.Equals(DataBaseType.GaussDB))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "PORT=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "5432");
                str += ";DATABASE=" + DB_NAME;
                str += ";HOST=" + conn_ip_port_set[0];
                str += ";PASSWORD=" + USER_PASSWORD;
                str += ";USER ID=" + USER_NAME;
            }
            else if (DB_TYPE.Equals(DataBaseType.SybaseASE))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Data Source=" + conn_ip_port_set[0];
                str += ";Port=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "5000");
                str += ";Database=" + DB_NAME;
                str += ";UID=" + USER_NAME;
                str += ";PWD=" + USER_PASSWORD;
                if (conn_ip_port_set.Length > 2) str += ";CharSet=" + conn_ip_port_set[2];
                str += ";EnableBulkLoad=1";
            }
            else if (DB_TYPE.Equals(DataBaseType.SQLite))
            {
                str = "Data Source=" + System.IO.Path.Combine(DB_IP, DB_NAME);
            }
            else if (DB_TYPE.Equals(DataBaseType.MongoDB))
            {
                str = "mongodb://" + USER_NAME + ":" + USER_PASSWORD + "@" + DB_IP;
            }
            else if (DB_TYPE.Equals(DataBaseType.DaMeng))
            {
                str = "Server=" + DB_IP + "; User Id=" + USER_NAME + "; PWD=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.Kingbase))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Server=" + conn_ip_port_set[0];
                str += ";Port=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "54322");
                str += ";Database=" + DB_NAME;
                str += ";User ID=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.ClickHouse))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Host=" + conn_ip_port_set[0];
                str += ";Port=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "9000");
                str += ";Database=" + DB_NAME;
                str += ";User=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
                str += ";Compressor=" + (conn_ip_port_set.Length > 2 ? conn_ip_port_set[2] : "lz4") + ";Compress=False;BufferSize=32768;SocketTimeout=10000;CheckCompressedHash=False";
            }
            else if (DB_TYPE.Equals(DataBaseType.Teradata))
            {
                string[] conn_ip_port_set = DB_IP.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                str = "Data Source=" + conn_ip_port_set[0];
                str += ";Port Number=" + (conn_ip_port_set.Length > 1 ? conn_ip_port_set[1] : "1025");
                str += ";Database=" + DB_NAME;
                str += ";User Id=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.Access))
            {
                str = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " + System.IO.Path.Combine(DB_IP, DB_NAME);
                str += " ;Persist Security Info=True;Jet OLEDB:Database Password=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.Dbf))
            {
                str = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " + System.IO.Path.Combine(DB_IP, DB_NAME);
                str += ";extended properties=dbase iv;user id=admin;password=" + USER_PASSWORD;
            }
            else if (DB_TYPE.Equals(DataBaseType.ODBC))
            {
                str = "Dsn=" + DB_IP;
                if (DB_NAME.Trim().Length > 0)
                    str += ";DataBase=" + DB_NAME;
                if (USER_NAME.Trim().Length > 0)
                    str += ";Uid=" + USER_NAME;
                if (USER_PASSWORD.Trim().Length > 0)
                    str += ";Pwd=" + USER_PASSWORD;
            }
            else
            {
                str = "Provider=" + DB_NAME;
                str += ";Data Source=" + DB_IP;
                str += ";Persist Security Info=True;User ID=" + USER_NAME;
                str += ";Password=" + USER_PASSWORD;
            }
            return str;
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <returns>XML</returns>
        public string ToXml()
        {
            StringBuilder sb = new StringBuilder();
            using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb))
            {
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(DbItem));
                serializer.Serialize(writer, this);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="pXml">XML</param>
        /// <returns>对象</returns>
        public static DbItem FromXml(string pXml)
        {
            DbItem item = null;
            using (System.IO.StringReader strReader = new System.IO.StringReader(pXml))
            {
                using (System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(strReader))
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(DbItem));
                    item = (serializer.Deserialize(xmlReader) as DbItem);
                }
            }
            return item;
        }
    }

    /// <summary>
    /// 数据库项目集合
    /// </summary>
    public class DbItemCollection : List<DbItem>
    {
        /// <summary>
        /// 按数据库编号获取项目
        /// </summary>
        /// <param name="db_no">数据库编号</param>
        /// <returns>数据库项目</returns>
        public DbItem GetByNo(int db_no)
        {
            DbItem item = null;
            for (int i = 0; i < base.Count; i++)
            {
                if (base[i].DB_NO == db_no)
                {
                    item = base[i];
                    break;
                }
            }
            return item;
        }
    }
}
